package win.devhu.onestation.controller;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

import org.apache.commons.dbutils.BasicRowProcessor;
import org.apache.commons.dbutils.GenerousBeanProcessor;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.RowProcessor;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.javalin.http.Context;
import io.javalin.http.Handler;
import io.javalin.plugin.openapi.annotations.*;
import win.devhu.onestation.model.RestfulResponse;
import win.devhu.onestation.model.User;
import win.devhu.onestation.utils.SqliteDBUtil;
import win.devhu.onestation.utils.StringUtil;

/**
 * 登录注册
 */
public class LoginController {

	private static StringUtil stringUtil = new StringUtil();
	private static Logger logger = LoggerFactory.getLogger(LoginController.class);

	// 登录
	@OpenApi(tags = {"user"},summary = "用户登录",queryParams = {
			@OpenApiParam(name = "username", type = String.class, description = "用户名"),
			@OpenApiParam(name = "password", type = String.class, description = "密码") },
			responses = { @OpenApiResponse(status = "200", content = @OpenApiContent(from = RestfulResponse.class)) })
	public static Handler handleSigninPost = ctx -> {

		if (!authVerify(ctx)) {
			ctx.json(new RestfulResponse(200, "用户名或密码错误"));
		} else {
			ctx.sessionAttribute("saturn", stringUtil.base64Encode(stringUtil.timeMillis())); // 通过 saturn 记录登录会话
			ctx.json(new RestfulResponse(302, "/index"));
			// ctx.redirect("/index"); //此处直接302跳转
			// ajax请求无法处理，原因：https://www.cnblogs.com/dudu/p/ajax_302_found.html
		}
	};

	// 注册
	@OpenApi(tags = {"user"},summary = "用户注册",description = "用户注册",queryParams = {
			@OpenApiParam(name = "username", type = String.class, description = "用户名"),
			@OpenApiParam(name = "password", type = String.class, description = "密码") },
			responses = { @OpenApiResponse(status = "200", content = @OpenApiContent(from = RestfulResponse.class)) })
	public static Handler handleSignupPost = ctx -> {
		String uname = ctx.formParam("username");
		String password = ctx.formParam("password");
		String sSql = "select count(id) from user where user.uname = ?";
		String inSql = "insert into user (uname, password) values (?, ?)";
		QueryRunner runner = new QueryRunner();
		Connection conn = SqliteDBUtil.getConnection();
		try {
			int count = ((Number) runner.query(conn, sSql, new ScalarHandler<Long>(), uname)).intValue();
			if (1 == count) {
				ctx.json(new RestfulResponse(200, "用户已存在"));
			} else {
				runner.insert(conn, inSql, new ScalarHandler<Object>(), uname, stringUtil.encrypt32(password));
				ctx.json(new RestfulResponse(200, "注册成功"));
			}
			conn.close();
		} catch (SQLException e) {
			ctx.json(new RestfulResponse(500, "注册失败:" + e));
		}
	};

	// 退出登录
	@OpenApi(tags = {"user"},summary = "退出登录")
	public static Handler handleLogoutPost = ctx -> {
		ctx.sessionAttribute("saturn", null);
		ctx.json(new RestfulResponse(302));
	};

	// 登录日志
	@OpenApi(tags = {"user"},summary = "获取登录日志")
	public static Handler handleEntryLogGet = ctx -> {
		String sql = "select * from user;";
		QueryRunner runner = new QueryRunner();
		Connection conn = SqliteDBUtil.getConnection();
		try {
			// 处理数据库字段为下划线，JAVA字段名为驼峰的情况
			RowProcessor processor = new BasicRowProcessor(new GenerousBeanProcessor());
			// BeanListHandler使用示例
			List<User> users = runner.query(conn, sql, new BeanListHandler<User>(User.class, processor));
			ctx.json(new RestfulResponse(200, null, users)); // 返回接口数据
			conn.close();
		} catch (SQLException e) {
			ctx.json(new RestfulResponse(500, "查询失败:" + e));
		}
	};

	// 登录验证
	private static Boolean authVerify(Context ctx) {
		String uname = ctx.formParam("username");
		String password = ctx.formParam("password");
		String sql = "select password from user where uname = ?;";
		QueryRunner runner = new QueryRunner();
		Connection conn = SqliteDBUtil.getConnection();
		try {
			String pwd = runner.query(conn, sql, new ScalarHandler<String>(), uname);
			if(pwd != null) {
				//String uSql = "update user set last_login_time=CURRENT_TIMESTAMP where uname=?";	//For Mysql
				String uSql = "update user set last_login_time=(datetime('now','localtime')) where uname=?";	//For Sqlite
				if (pwd.equals(stringUtil.encrypt32(password))) { // 校验登录密码
					runner.update(conn, uSql, uname); // 更新最后一次登录时间
					logger.info(uname + "登录成功");
					conn.close();
					return true;
				} else {
					conn.close();
					return false;	//查询密码结果为null的情况
				}	
			}else {
				return false;
			}

		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		}
	}

	// 页面访问权限控制
	public static Handler ensureLoginBeforeViewing = ctx -> {
		if (ctx.sessionAttribute("saturn") == null && (
		// 以下页面未登录强制跳转登录页
		ctx.path().startsWith("/index") || ctx.path().startsWith("/otherpage"))) {
			ctx.redirect("/login");
		}
	};
}
